import { Inject, Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { FindOptionsWhere, In, Like, Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { LoginUserDto } from './dto/login-user.dto';
import * as bcrypt from 'bcryptjs';
import { JwtService } from '@nestjs/jwt';
import Constants from '../common/constants';
import { RedisService } from '../redis/redis.service';
import { Role } from '../role/entities/role.entity';
import { CreateRoleDto } from '../role/dto/create-role.dto';
import { QueryUserDto } from './dto/query-user.dto';
import { Equals } from 'class-validator';
import Config from '../config/config';
import { WhereClauseCondition } from 'typeorm/query-builder/WhereClause';
import RoleEnum from '../role/entities/RoleEnum';

@Injectable()
export class UsersService {
  constructor(
    private jwtService: JwtService,
    @InjectRepository(User) private readonly user: Repository<User>,
    @InjectRepository(Role) private readonly role: Repository<Role>,
    @Inject() private redisService: RedisService,
  ) {}

  async create(createUserDto: CreateUserDto) {
    try {
      const usernameExists = await this.user.findOne({
        where: {
          username: createUserDto.username,
        },
      });
      if (usernameExists) {
        return {
          status: 400,
          msg: `用户名${createUserDto.username}重复`,
        };
      }

      const emailExists = await this.user.findOne({
        where: {
          email: createUserDto.email,
        },
      });
      if (emailExists) {
        return {
          status: 400,
          msg: `用户邮箱${createUserDto.email}重复`,
        };
      }

      await this.user.manager.transaction(async (manager) => {
        // 默认123456
        if (!createUserDto.password) createUserDto.password = '123456';
        //   创建用户
        let role = null;
        if (!createUserDto.role) {
          role = await this.role.findOne({
            where: {
              roleName: RoleEnum.Anonymous,
            },
          });
        } else {
          role = await this.role.findOne({
            where: {
              id: createUserDto.role.id,
            },
          });
        }
        const user = this.user.create({
          ...createUserDto,
          role,
          password: bcrypt.hashSync(createUserDto.password, 10),
        });

        // 将角色关联到用户
        // user.roles = roles;
        console.log('users.service.ts-user-user', user);
        await manager.save(user);
      });
      return {
        msg: '创建成功',
      };
    } catch (e) {
      return {
        msg: e,
      };
    }
  }

  async assignRolesToUser(userId: string, roleId: string) {
    // 首先，找到用户和角色实体
    const user = await this.user.findOne({
      where: {
        id: userId,
      },
      relations: ['role'],
    });
    if (!user) {
      return {
        msg: '找不到该用户',
      };
    }
    const role = await this.role.findOne({
      where: {
        id: roleId,
      },
    });

    user.role = role;
    // 保存更新后的用户
    await this.user.save(user);
    return {
      msg: '给用户分配角色成功',
    };
  }

  /**
   *
   * @param query 前端传递的查询条件,包含分页参数
   * @param whereCondition 根据角色信息生成的查询where条件
   */
  async findAll(query: QueryUserDto, whereCondition: FindOptionsWhere<User>) {
    const total = await this.user.count({
      where: whereCondition,
    });
    // 总的分页数
    const totalPages = +Math.ceil(total / +query.pageSize);
    console.log('users.service.ts-findAll-totalPages', totalPages);
    // 查询的是最后一页数据
    if (+query.currentPage === totalPages) {
      const rest = total % +query.pageSize;
      query.pageSize = rest === 0 ? query.pageSize : +rest;
    }
    let userList = await this.user.find({
      where: whereCondition,
      relations: ['role', 'role.permissions'],
      select: [],
      // 跳过前page页的数据，page从1开始
      ...(query.currentPage && {
        skip: (+query.currentPage - 1) * +query.pageSize,
      }),
      // 每页显示pageSize条数据
      ...(query.pageSize && {
        take: +query.pageSize,
      }),
    });
    // 过滤不显示密码
    userList = userList.map((item) => {
      item.password = '';
      return item;
    });

    return {
      data: {
        userList,
        total,
        currentPage: +query.currentPage,
        pageSize: +query.pageSize,
      },
    };
  }

  async findOne(id: string) {
    const user = await this.user.findOne({
      where: { id, is_deleted: false },
      relations: ['role', 'role.permissions'],
    });
    if (!user) {
      return {
        msg: '该用户不存在',
        status: 201,
      };
    }
    return {
      data: user,
      msg: '查询用户成功',
    };
  }

  async update(id: string, updateUserDto: UpdateUserDto) {
    const user = await this.user.findOne({
      where: {
        id,
        is_deleted: false,
      },
    });
    if (!user) {
      return {
        msg: `User with ID "${id}" not found`,
      };
    }
    // 更新用户信息，这里可以根据实际情况来更新字段
    await this.user.save({
      ...user,
      ...updateUserDto,
      //   使用默认新密码，否则使用旧密码
      password: bcrypt.hashSync(updateUserDto.password, 10) || user.password,
    });
    return {
      msg: `用户信息更新成功`,
    };
  }

  async login(loginUserDto: LoginUserDto) {
    if (Config.captchaConfig.enable) {
      const redisCaptcha = await this.redisService.get('captcha');
      const { code: captcha } = loginUserDto;
      if (!captcha) {
        return {
          msg: `请输入验证码`,
          code: 201,
        };
      }
      if (redisCaptcha.toLowerCase() !== captcha.toLowerCase()) {
        return {
          msg: '验证码错误',
          code: 201,
        };
      }
      await this.redisService.del('captcha');
    }

    const loginUser = await this.user.findOne({
      where: {
        username: loginUserDto.username,
        is_deleted: false,
      },
      relations: ['role', 'role.permissions'],
    });

    if (!loginUser || Object.keys(loginUser).length === 0) {
      return {
        msg: '没有此用户,请检查用户名或密码',
        status: 201,
      };
    }
    if (loginUser.is_disabled) {
      return {
        msg: '用户被禁用,请联系管理员',
        status: 403,
      };
    }
    if (bcrypt.compareSync(loginUserDto.password, loginUser.password)) {
      const payload = { sub: loginUser.id, username: loginUser.username };

      const accessToken = await this.jwtService.signAsync(payload);
      // 以用户id为key，生成的token为value，缓存到redis中并设置过期时间
      await this.redisService.set(`${loginUser.id}`, accessToken);
      // 以生成的token为key，用户信息为value，缓存到redis中并设置过期时间
      await this.redisService.set(
        accessToken,
        JSON.stringify({ ...loginUser, password: '' }),
      );
      return {
        data: {
          [Constants.Access_Token]: accessToken,
        },
      };
    } else {
      return {
        msg: '用户名或密码错误',
      };
    }
  }

  // async register(createUserDto: CreateUserDto) {
  //   const registerUser = this.user.create({
  //     ...createUserDto,
  //     password: bcrypt.hashSync(createUserDto.password, 10),
  //   });
  //   await this.user.save(registerUser);
  //   return {
  //     msg: '注册成功',
  //   };
  // }

  async logout(token: string) {
    // 以生成的token为key，用户信息为value，缓存到redis中并设置过期时间
    const userInfo = (await this.redisService.get(token)) as unknown as User;
    await this.redisService.del(token);
    await this.redisService.del(`${userInfo.id}`);
    return {
      msg: '退出登录成功',
    };
  }

  async userInfo(token: string) {
    const userInfo = await this.redisService.get(token);
    if (!userInfo) {
      return {
        msg: '没有此用户信息',
      };
    }
    return {
      data: JSON.parse(userInfo),
      msg: '获取用户信息成功',
    };
  }

  async batchDelete(ids: string[]) {
    const users = await this.user.findBy({
      id: In(ids),
    });
    console.log('users.service.ts-batchDelete-users', ids);
    users.forEach((user) => (user.is_deleted = true));
    await this.user.save(users);

    return {
      msg: '批量删除成功',
    };
  }
}
